#include "GLUtil.h"
#include <gl/glut.h>
#include "ArcBall.h"
#include <stdio.h>


Matrix4fT   Transform   = {  1.0f,  0.0f,  0.0f,  0.0f,				// NEW: Final Transform
	0.0f,  1.0f,  0.0f,  0.0f,
	0.0f,  0.0f,  1.0f,  0.0f,
	0.0f,  0.0f,  0.0f,  1.0f };

Matrix3fT   LastRot     = {  1.0f,  0.0f,  0.0f,					// NEW: Last Rotation
	0.0f,  1.0f,  0.0f,
	0.0f,  0.0f,  1.0f };

Matrix3fT   ThisRot     = {  1.0f,  0.0f,  0.0f,					// NEW: This Rotation
	0.0f,  1.0f,  0.0f,
	0.0f,  0.0f,  1.0f };

ArcBallT    ArcBall(640.0f, 480.0f);				                // NEW: ArcBall Instance
Point2fT    MousePt;												// NEW: Current Mouse Point

bool isClick = false;
bool isDrag = false;
bool isZoom = false;

int sx, sy;

double zoom = 5;

extern void TrenderMesh();
extern void TrenderVector();
void ArenderMesh();
extern bool compute;
extern double colorScale;

void reshape(GLint width, GLint height)
{
	glViewport (0, 0, (GLsizei)(width), (GLsizei)(height));				// Reset The Current Viewport
	glMatrixMode (GL_PROJECTION);										// Select The Projection Matrix
	glLoadIdentity ();													// Reset The Projection Matrix
	gluPerspective (45.0f, (GLfloat)(width)/(GLfloat)(height),			// Calculate The Aspect Ratio Of The Window
		0.001f, 10000.0f);		
	glMatrixMode (GL_MODELVIEW);										// Select The Modelview Matrix
	glLoadIdentity ();													// Reset The Modelview Matrix

	ArcBall.setBounds((GLfloat)width, (GLfloat)height); 
}

void keyboard(unsigned char p_key, int p_x, int p_y){

	switch (p_key)
	{
	case 'a':
		colorScale /= 2.0;
		glutPostRedisplay();
		break;

	case 's':
		colorScale *= 2.0;
		printf("hello");
		glutPostRedisplay();
		break;

	case 'd':
		//kLevel += 1;
		compute = true;
		glutPostRedisplay();
		break;

	case 'f':
		//kLevel -= 1;
		compute = true;
		glutPostRedisplay();
		break;
	}
}

void mouse(int button, int state, int x, int y)
{
	if (button == GLUT_LEFT_BUTTON)
	{
		if (state == GLUT_DOWN)
		{
			isClick = true;

			sx = x;
			sy = y;

		}else if (state == GLUT_UP)
		{
			isClick = false;
		}
	}

	if (button == GLUT_MIDDLE_BUTTON)
	{
		if (state == GLUT_UP)
		{
			isZoom = false;

		}else if (state == GLUT_DOWN)
		{
			isZoom = true;

			sx = x;
			sy = y;
		}
	}

}

void motion(int x, int y)
{
	MousePt.s.X = x;
	MousePt.s.Y = y;

	if (isDrag)
	{
		if (isClick)
		{
			Quat4fT     ThisQuat;

			ArcBall.drag(&MousePt, &ThisQuat);						// Update End Vector And Get Rotation As Quaternion
			Matrix3fSetRotationFromQuat4f(&ThisRot, &ThisQuat);		// Convert Quaternion Into Matrix3fT
			Matrix3fMulMatrix3f(&ThisRot, &LastRot);				// Accumulate Last Rotation Into This One
			Matrix4fSetRotationFromMatrix3f(&Transform, &ThisRot);	// Set Our Final Transform's Rotation From This One
		}else{
			isDrag = false;
		}

	}else{
		if (isClick)
		{
			isDrag = true;
			LastRot = ThisRot;
			ArcBall.click(&MousePt);
		}
	}

	if (isZoom)
	{
		zoom += (y - sy) * 0.01;
	}
}

void display(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	gluLookAt(0, 0, zoom, 0, 0, 0, 0, 1, 0);

	float tt=20;

	glPushMatrix();													// NEW: Prepare Dynamic Transform
	glMultMatrixf(Transform.M);										// NEW: Apply Dynamic Transform
	//glColor3f(0.75f,0.75f,1.0f);
	//glutSolidSphere(2, 10, 10);
	ArenderMesh();
	glPopMatrix();													// NEW: Unapply Dynamic Transform	







	glutSwapBuffers();
	glutPostRedisplay();

}

